Zero-trust · Malware scanning · Time-limited access
SecureShare Hub. Azure native file sharing with enforced sign-in & content scanning.
A hardened blueprint for distributing files from fully private Azure Blob Storage using Easy Auth–enforced
Microsoft sign-in, short-lived user delegation SAS URLs, and an event-driven malware scanning pipeline.
Every download is authenticated, time-bounded, and auditable from code to storage.
Azure Functions · Python
Terraform IaC
GitHub Actions · OIDC
Easy Auth · Entra ID
Blob Storage (private only)
Event Grid malware pipeline
Access model: private Blob + user delegation SAS only
SAS lifetime: typically 15–30 minutes
CI/CD: passwordless GitHub Actions via OIDC
↗
View full project on GitHub
Architecture snapshot
Full diagram in gallery below.
GitHub Actions → Terraform → Function App
Easy Auth (Entra ID) → Managed Identity
Upload → incoming-raw → Event Grid → Scan Function
→ safe-files / quarantine → SAS → Client download
Overview
What SecureShare Hub solves
Many teams still share sensitive files using public blob URLs, long-lived SAS tokens, or emailed attachments.
SecureShare Hub shows how to do it properly on Azure: enforce Microsoft sign-in for every request, keep storage
completely private, scan uploads before promotion, and issue only short-lived read-only links.
The pattern
Zero-trust file distribution, end-to-end.
Files never live in public containers. Users never see storage keys or connection strings. Every download
passes through identity, authorization, and an audited SAS-issuance step, while an event-driven pipeline
scans new uploads before they become eligible for sharing.
- Storage accounts created with "allow_blob_public_access = false".
- Easy Auth + Entra ID forces sign-in for HTML and APIs – there is no anonymous entry point.
- Uploads land in an untrusted "incoming-raw" container, then flow through a scan Function.
- Only clean files are promoted into "safe-files"; suspicious content is diverted to
"quarantine" and cleaned up automatically.
- Read-only user delegation SAS URLs are created per request, for a tight expiry window.
Key outcomes
Secure by default, auditable by design.
The platform is built as a realistic reference implementation for Azure-native secure sharing. It also
doubles as a portfolio project demonstrating IaC, automation, identity, and security controls working
together.
Enforced Microsoft sign-in (Easy Auth)
Private Blob Storage only
Event Grid malware pipeline
Versioning + soft delete
Lifecycle policies (cost + retention)
GZRS storage redundancy
Passwordless CI/CD with OIDC
Zero-trust principles & capabilities
Zero Trust by Design
SecureShare Hub uses private storage, enforced sign-in, short-lived links, and a full content-safety pipeline.
Every part of the system follows zero-trust principles—treat the network as untrusted, keep data hidden, rely on identity and policy,
and reduce the blast radius of any token or file.
Zero-trust principle
Private by default
Storage accounts disable blob public access at the account level. All Blob containers are private, and the
only valid access path is via the hardened Function backend issuing user delegation SAS URLs.
Private Blob Storage
RBAC + managed identity
Zero-trust principle
Identity-driven access
App Service Authentication (Easy Auth) with Entra ID is turned on for the entire Function App. Any
unauthenticated request is redirected to Microsoft login – there is no public HTML and no anonymous API
surface.
The backend reads X-MS-CLIENT-PRINCIPAL and related headers to identify the caller and
derive roles and policies.
Easy Auth enforced
Entra ID tokens only
Zero-trust principle
Time-limited, least-privilege links
The Function uses the Storage SDK with a user delegation key to mint read-only SAS tokens that are scoped
to a single blob and expire after a short window (typically 15–30 minutes). After that, even a leaked URL
is useless.
Read-only SAS
Per-file scope
Tight expiry
Content safety
Event-driven malware scanning
Uploads enter an incoming-raw container. Azure Event Grid watches for new blobs and triggers
a dedicated Scan Function. That Function downloads the content, runs AV checks, and either promotes the
file into safe-files or moves it into quarantine with metadata
scanStatus set accordingly.
incoming-raw → safe-files/quarantine
Event Grid trigger
Resilience & lifecycle
Versioning, soft delete, and DR
Blob versioning and 30-day soft delete are enabled on the Storage Account, with GZRS redundancy for
zone-plus-region resilience. Management policies move older blobs to Cool tier and eventually delete
them, while quarantine data is cleaned up after a short retention window.
Versioning + soft delete
Lifecycle to Cool + delete
GZRS replication
Platform feature
IaC + passwordless CI/CD
Terraform modules create the resource group, Function App, Storage, Key Vault, Event Grid topics, and
role assignments. GitHub Actions deploys the stack using OpenID Connect federation, so there are no
long-lived client secrets in pipeline configuration.
Terraform modules
GitHub Actions + OIDC
No stored SP keys
Azure architecture
From Commit to Secure Download.
SecureShare Hub uses nine tightly integrated components to move a file from upload to scan to signed download.
Every part of the architecture maps directly to a real Azure service and Terraform module, making the system fully rebuildable end to end.
Logical components
-
1
GitHub Actions CI/CD
deploy-infrastructure · deploy-application
Terraform and the Python Function are deployed through OIDC-based workflows, avoiding stored
service principal secrets.
OIDC login
Separate infra / app stages
-
2
Terraform IaC layer
Resource Group · Storage · Function App · Key Vault · Event Grid
Opinionated Terraform modules enforce private storage, managed identities, minimum RBAC roles, and
storage lifecycle rules.
-
3
Function App with Easy Auth
App Service Authentication + Entra ID
App Service Authentication is set to "On" and "Require authentication". Any unauthenticated request
is redirected to Microsoft login before HTML or APIs are reachable.
X-MS-CLIENT-PRINCIPAL
Enforced sign-in
-
4
Python API backend
SAS issuance & authorization checks
A Python Function handles authenticated requests, derives identity from platform headers, and issues
user delegation SAS URLs only for authorized users and clean files.
-
5
Azure Key Vault
Non-identity secrets only
Key Vault stores app configuration and integration secrets. Storage access relies on managed
identity + RBAC instead of connection strings.
-
6
Blob Storage account
incoming-raw · safe-files · quarantine
Storage accounts are private, with three containers: untrusted uploads, clean files, and
quarantined items. Versioning, soft delete, and lifecycle policies are configured via Terraform.
-
7
Event Grid + Scan Function
BlobCreated → scan → promote / quarantine
Event Grid subscribes to BlobCreated events in incoming-raw and triggers a scanning
Function that decides whether to promote the file to safe-files or move it to
quarantine.
-
8
User delegation SAS generator
Per-file, read-only download links
SAS URLs are built using the Function's managed identity and user delegation keys, with
time-boxed permissions and audit logging.
-
9
Client applications
Portal / internal tools / external clients
Any authenticated Entra ID user can hit the Function endpoint. The "client" may be a web portal, an
internal tool, or a partner application that exchanges SAS links behind the scenes.
End-to-end workflow (high-level)
-
1
Developer pushes to GitHub
Code changes (Terraform, Functions, or configuration) land in the main repo.
-
2
CI/CD deploys infra & app
GitHub Actions authenticates into Azure using OIDC, runs Terraform apply, and then publishes the
Function App.
-
3
User hits SecureShare Hub URL
Because App Service Authentication is enabled and required, the user is redirected to
login.microsoftonline.com and must sign in with their Microsoft 365 account.
-
4
Upload into incoming-raw
The front-end or a back-office process uploads files into the untrusted
incoming-raw container using the backend.
-
5
Event-driven malware scan
Event Grid emits a BlobCreated event, which triggers the Scan Function to download and scan the
file.
-
6
Promote or quarantine
Clean files are copied into safe-files with metadata
scanStatus=clean. Suspicious files are moved into quarantine and tagged
accordingly.
-
7
User requests a download
An authenticated user calls the Function to get a secure link for a given file.
-
8
Backend issues SAS (if safe)
The Function resolves identity, checks authorization, verifies scanStatus=clean on the
blob, and then issues a short-lived read-only user delegation SAS URL.
-
9
Client downloads directly from Storage
The browser or client streams the file directly from Blob Storage using the SAS URL. After the
expiry window, the link automatically stops working.
Security controls & hardening
Defense-in-Depth Architecture.
SecureShare Hub is built to meet strict security expectations, layering protection across identity, storage, automation, and content safety.
No public storage, no long-lived secrets, and no unscanned files, every layer reduces unnecessary trust and stands up to serious security scrutiny.
Storage hardening
- Blob public access is disabled on the Storage Account; all containers are private.
- Three-container pattern: "incoming-raw" (untrusted), "safe-files" (clean only),
"quarantine" (suspicious).
- Blob versioning and 30-day soft delete protect against overwrite / delete mistakes.
- Lifecycle policies move long-lived content to Cool tier and delete it after retention, while
quarantine data is purged sooner.
Identity-first access
- App Service Authentication (Easy Auth) with Entra ID is configured to require authentication for all
routes.
- Any unauthenticated request is redirected to Microsoft login; there's no anonymous HTML or
Function endpoint.
- The backend derives identity from "X-MS-CLIENT-PRINCIPAL" rather than trusting client-supplied
identifiers.
- Managed identity + Storage RBAC replace shared keys and connection strings.
Malware & content safety
- Uploads are treated as untrusted input and stored only in "incoming-raw".
- Event Grid feeds a Scan Function that inspects the content and assigns "scanStatus"
metadata.
- The SAS generation Function only ever targets "safe-files" and checks for
"scanStatus=clean" before issuing a link.
- Suspicious content is isolated in "quarantine" and pruned automatically by lifecycle
rules.
Secrets & CI/CD
- Key Vault stores non-identity configuration secrets with tightly scoped access policies.
- Storage access avoids connection strings and account keys entirely, relying on managed identity.
- GitHub Actions uses OIDC federation to log in to Azure; no client secret is stored in the repo.
- Terraform state and deployments are repeatable, traceable, and environment-aware.
Future evolution
With the foundations in place (Easy Auth, private storage, scanning pipeline, lifecycle, and DR), future
iterations can focus on authorization depth and multi-tenant capabilities:
- Integrate Entra ID groups / roles for fine-grained per-folder permissions.
- Use private endpoints and Azure Firewall / Application Gateway for additional network isolation.
- Stream logs into Log Analytics + Sentinel with alert rules for unusual download activity.
- Expose an admin UI for revoking links, reviewing quarantine, and auditing access.
Screenshot gallery
Key Highlights of SecureShare Hub.
These screenshots showcase the most important parts of the platform—from the core architecture and authentication flow to the scanning pipeline,
container layout, and lifecycle configuration. Each one gives reviewers a clear view of how the system works behind the scenes..
Key screenshot
Architecture diagram
Overall system flow from CI/CD to scanned, signed file download.
Use this in portfolios and interviews to explain the whole pattern in 60 seconds.
Key screenshot
Easy Auth configuration
Proves that no anonymous HTML or API calls are allowed – sign-in is mandatory.
Crucial when explaining “identity-first access”.
Key screenshot
Container layout
The three-container pattern that underpins the malware pipeline.
Use this to explain how untrusted uploads are separated from clean files.
Key screenshot
Versioning & lifecycle
Shows resilience (undo mistakes) and cost-aware retention at the storage layer.
Important when discussing DR and compliance.
Event Grid → Scan Function
Shows how uploads trigger scanning automatically via BlobCreated events.
Pairs nicely with the Scan Function code screenshot.
Scan Function implementation
Backend logic for scanning and promoting files based on metadata.
Good code-level view to prove this isn't just a diagram.
CI/CD pipelines
Shows passwordless deployment using OIDC and split infra / app stages.
Useful when talking about DevOps practices.
Terraform stack
Evidence that the entire platform is provisioned and managed as code.
Good companion shot for IaC discussions.
Download API Function
Where identity, authorization, scanning metadata, and SAS issuance intersect.
Central to explaining the zero-trust access model.
Key Vault
Shows how configuration secrets are stored and scoped to the Function identity.
Reinforces the “no storage keys in vault” pattern.
Client UI
Example of how end users interact with SecureShare Hub.
Optional, but helpful when telling the end-user story.
Audit logs
Download and SAS events centralized in Log Analytics / App Insights.
Great proof point for compliance and observability.
Demo – end-user experience
How SecureShare Works
SecureShare Hub lets users sign in, upload a file, watch it get scanned instantly,
and receive a short-lived secure link—all without the file ever being exposed public
The user hits the SecureShare Hub URL and is immediately redirected to Microsoft login. No guest,
anonymous, or link-only access is possible.
The web UI or a back-office tool uploads files into the incoming-raw container via the
authenticated Function backend. At this point the file is untrusted and not yet shareable.
Event Grid detects the BlobCreated event and triggers the Scan Function, which downloads the file,
runs AV checks, and promotes it to safe-files or moves to quarantine.
When the file is clean, the user requests a link. The backend validates identity, checks
scanStatus=clean, and issues a short-lived, per-file user delegation SAS URL for direct
download from Blob Storage.
Tech stack
Azure-native, IaC-driven, and CI/CD-first from day one.
SecureShare Hub follows a true production, first approach Azure native services,
identity aware Functions, private storage, event-driven processing and fully repeatable infrastructure deployed through Terraform and CI/CD from day one.
Core platform
- Azure Functions (Python) for SAS issuance and malware scanning.
- Azure Blob Storage with private access, versioning, and lifecycle policies.
- Azure Event Grid for BlobCreated → Scan Function orchestration.
- Azure Key Vault for configuration secrets (non-storage identity).
Identity, security & networking
- Microsoft Entra ID + App Service Authentication (Easy Auth).
- Managed identity + RBAC for storage access (no connection strings).
- Short-lived user delegation SAS for per-file, read-only access.
- Designed to extend with private endpoints, Firewall, and Sentinel.
DevOps & observability
- Terraform for resource groups, storage, Functions, Key Vault, Event Grid.
- GitHub Actions with OIDC (passwordless Azure login).
- Split infra/app workflows for safer deployments.
- Log Analytics / App Insights for SAS issuance and download audit trails.
Project snapshot
SecureShare Hub
A zero-trust, scan-first Azure file sharing pattern with enforced Microsoft sign-in, private-only Blob
Storage, short-lived user delegation SAS URLs, and Terraform driven lifecycle, DR, and CI/CD.
Zero trust Azure
Python Azure Functions
Terraform IaC
GitHub Actions + OIDC
Easy Auth (Entra ID)
Event Grid malware pipeline
Access model
Private Blob + per-file user delegation SAS only
SAS lifetime
Configurable, typically 15–30 minutes
Authentication
Easy Auth (Entra ID), sign-in required for all requests
Content safety
incoming-raw → Event Grid → Scan Function → safe-files/quarantine
Resilience
Blob versioning, soft delete, lifecycle policies, GZRS
CI/CD & IaC
Terraform modules + GitHub Actions with OIDC federation
Jump to full engineering deep dive →
Challenges & lessons learned
What I Learned Building SecureShare Hub.
This section highlights the real challenges, trade-offs, and fixes I encountered throughout the project
and what I would confidently repeat in future builds..
A naive design would put everything into a single container with a "scanStatus" flag. That
makes it too easy for misconfigurations or bugs to expose unscanned files.
- Solution: separate "incoming-raw", "safe-files", and "quarantine"
at the container level.
- Benefit: simplifies access rules – SAS issuance Functions only ever look at "safe files".
- Trade-off: slightly more storage operations (copy/move), but much clearer security boundaries.
Easy Auth abstracts token validation but exposes identity through headers like
"X-MS-CLIENT-PRINCIPAL". Handling this safely is not obvious at first.
- Challenge: decoding the principal header and avoiding trusting client-supplied IDs.
- Solution: central helper in the Function code that parses, validates, and normalizes the identity
object.
- Outcome: authorization checks are expressed in terms of roles / groups, not raw IDs from the query
string.
Very short SAS lifetimes are more secure, but can frustrate users if downloads are slow or they share a
link just before expiry.
- Experimented with lifetimes between 5 and 60 minutes.
- Settled on a default of 15–30 minutes, with room for policy-based adjustments.
- Idea for future: add a “re-issue link” button in the UI with extra logging.
Using client secrets in GitHub Actions would have been the easiest path, but it contradicts the
project's zero-trust goals.
- Solution: use OpenID Connect (OIDC) federation for GitHub → Azure login.
- Benefit: no long-lived credentials in the repo or pipeline.
- Lesson: infrastructure pipelines should follow the same security principles as application code.